#include "DXUT.h"
#include "SceneObject.h"


 

CMeshInstance::CMeshInstance()
{
	m_pMesh = NULL;
	m_pos = m_rot = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
	m_sca = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
}

CMeshInstance::CMeshInstance(CMesh *meshPtr)
{
	m_bDefaultMaterial=true;
	m_pMesh = meshPtr;
	m_pos = m_rot = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
	m_sca = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
}

D3DXMATRIX CMeshInstance::GetWorldMatrix()
{
	D3DXMATRIX p, r, s;
	D3DXMatrixTranslation(&p, m_pos.x, m_pos.y, m_pos.z);
	D3DXMatrixRotationYawPitchRoll(&r, m_rot.y, m_rot.x, m_rot.z);
	D3DXMatrixScaling(&s, m_sca.x, m_sca.y, m_sca.z);

	D3DXMATRIX world = s * r * p;
	return world;
}

void CMeshInstance::Render()
{
	LPDIRECT3DDEVICE9 pDevice=DXUTGetD3D9Device();
	if(m_pMesh != NULL)
	{
		pDevice->SetTransform(D3DTS_WORLD, &GetWorldMatrix());
		m_pMesh->Render(m_bDefaultMaterial);
	}
}

BoundingBox CMeshInstance::GetBoundingBox()
{
	//if(m_pMesh == NULL || m_pMesh->m_pMesh == NULL)return BBox();

	////	if(m_pMesh->m_pMesh->GetFVF() != ObjectVertex::FVF)		// XYZ and NORMAL and UV
	////	return BBox();

	//BBox bBox(D3DXVECTOR3(-10000.0f, -10000.0f, -10000.0f),
	//	D3DXVECTOR3(10000.0f, 10000.0f, 10000.0f));
	//D3DXMATRIX World = GetWorldMatrix();

	////Lock vertex buffer of the object
	//ObjectVertex* vertexBuffer = NULL;
	//BYTE * pBuffer;
	//DWORD NumBytesPerVertex=  m_pMesh->GetMesh()->GetNumBytesPerVertex(); 
	//D3DXVECTOR3 * pPoint;
	//m_pMesh->m_pMesh->LockVertexBuffer(0,(void**)&pBuffer);


	////For each vertex in the m_pMesh
	//for(int i=0;i<(int)m_pMesh->m_pMesh->GetNumVertices();i++)
	//{
	//	//Transform vertex to world space using the MESHINSTANCE
	//	//world matrix, i.e. the position, rotation and scale

	//	      D3DXVECTOR3 *  p =   (D3DXVECTOR3 *)(pBuffer+NumBytesPerVertex* i);
	//	D3DXVECTOR3 pos;
	//	D3DXVec3TransformCoord(&pos, p, &World);

	//	// Check if the vertex is outside the bounds
	//	// if so, then update the bounding volume
	//	if(pos.x < bBox.min.x)bBox.min.x = pos.x;
	//	if(pos.x > bBox.max.x)bBox.max.x = pos.x;
	//	if(pos.y < bBox.min.y)bBox.min.y = pos.y;
	//	if(pos.y > bBox.max.y)bBox.max.y = pos.y;
	//	if(pos.z < bBox.min.z)bBox.min.z = pos.z;
	//	if(pos.z > bBox.max.z)bBox.max.z = pos.z;
	//}

	//m_pMesh->m_pMesh->UnlockVertexBuffer();

	//return bBox;











	if(m_pMesh == NULL || m_pMesh->m_pMesh == NULL)return BoundingBox();

 
	BoundingBox bBox(D3DXVECTOR3(-10000.0f, -10000.0f, -10000.0f),
		D3DXVECTOR3(10000.0f, 10000.0f, 10000.0f));
	D3DXMATRIX World = GetWorldMatrix();

 
	ObjectVertex* vertexBuffer = NULL;
	m_pMesh->m_pMesh->LockVertexBuffer(0,(void**)&vertexBuffer);

 
	for(int i=0;i<(int)m_pMesh->m_pMesh->GetNumVertices();i++)
	{
 
		D3DXVECTOR3 pos;
		D3DXVec3TransformCoord(&pos, &vertexBuffer[i]._pos, &World);

 
		if(pos.x < bBox.min.x)bBox.min.x = pos.x;
		if(pos.x > bBox.max.x)bBox.max.x = pos.x;
		if(pos.y < bBox.min.y)bBox.min.y = pos.y;
		if(pos.y > bBox.max.y)bBox.max.y = pos.y;
		if(pos.z < bBox.min.z)bBox.min.z = pos.z;
		if(pos.z > bBox.max.z)bBox.max.z = pos.z;
	}

	m_pMesh->m_pMesh->UnlockVertexBuffer();

	return bBox;
}

BoundingSphere CMeshInstance::GetBoundingSphere()
{
	if(m_pMesh == NULL || m_pMesh->m_pMesh == NULL)return BoundingSphere();
	//if(m_pMesh->m_pMesh->GetFVF() != ObjectVertex::FVF)		// XYZ and NORMAL and UV
		//return BoundingSphere();

	BoundingBox bBox = GetBoundingBox();
	BoundingSphere bSphere;
	D3DXMATRIX World = GetWorldMatrix();
	bSphere.centre = (bBox.max + bBox.min) / 2.0f;

	ObjectVertex* vertexBuffer = NULL;
	m_pMesh->m_pMesh->LockVertexBuffer(0,(void**)&vertexBuffer);

	//Get radius
	for(int i=0;i<(int)m_pMesh->m_pMesh->GetNumVertices();i++)
	{
		D3DXVECTOR3 pos;
		D3DXVec3TransformCoord(&pos, &vertexBuffer[i]._pos, &World);

		float l = D3DXVec3Length(&(pos - bSphere.centre));
		if(l > bSphere.radius)
			bSphere.radius = l;
	}

	m_pMesh->m_pMesh->UnlockVertexBuffer();

	return bSphere;
}

void CMeshInstance::OnD3D9FrameRender( float fElapsedTime )
{
	LPDIRECT3DDEVICE9 pDevice=DXUTGetD3D9Device();
	if(m_pMesh != NULL)
	{
		pDevice->SetTransform(D3DTS_WORLD, &GetWorldMatrix());
		m_pMesh->Render(m_bDefaultMaterial);
	}
}





 